﻿using System;
using System.Collections.Generic;
using System.Linq;
using AMM.Business.Business;
using AMM.Business.Config;
using AMM.CustomClassLibrary;
using AMM.DataAccess.Store;
using AMM.Model;
using AMM.Model.Store;

namespace AMM.Business.Store {
    public class ProcurementOrderProcessor : BaseProcessor {

        private int _pageSize;
        private ProcurementOrderRepository _procurementOrderRepository;

        public ProcurementOrderProcessor(int pageSize = int.MaxValue) {
            this._pageSize = pageSize;
            this._procurementOrderRepository = new ProcurementOrderRepository(pageSize);
        }

        public ProcurementOrder FetchProcurementOrderById(int procurementOrderId) {
            try {
                return this._procurementOrderRepository.FetchProcurementOrderById(procurementOrderId);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("获取指定采购订单失败！");
            }
        }

        public List<ProcurementOrderDetailsViewModel> FetchProcurementOrderDetailsViewModelList(int procurementOrderId) {
            try {
                return this._procurementOrderRepository.FetchProcurementOrderByIdForView(procurementOrderId).ProcurementOrderDetails.Select(x => {
                    return new ProcurementOrderDetailsViewModel() {
                        Key = x.ProcurementOrderDetailsId,
                        DeliveryDate = x.DeliveryDate,
                        InStoreQuantity = x.InStoreQuantity,
                        MaterialCode = x.Material.Code,
                        MaterialName = x.Material.Name,
                        MaterialDescription = x.Material.Remarks,
                        SourceCode = x.Basic.Code,
                        SuspenseQuantity = x.SuspenseQuantity,
                        UnQualifiedQuantity = x.UnQualifiedQuantity,
                        Quantity = x.Quantity,
                        Price = x.Price,
                        Total = x.Total.Value,
                        CreatedBy = x.CreatedBy,
                        CreatedDatetime = x.CreatedDatetime,
                        ModifiedBy = x.ModifiedBy,
                        ModifiedDatetime = x.ModifiedDatetime
                    };
                }).ToList();
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("获取指定采购订单失败！");
            }
        }

        public List<ProcurementOrderViewModel> FetchProcurementOrderViewModelList(ProcurementOrderSearchModel searchModel, int pageIndex = 1) {
            try {
                List<ProcurementOrder> resultList = this._procurementOrderRepository.FetchProcurementOrderList(searchModel, pageIndex);
                return resultList.Select(x => {
                    return new ProcurementOrderViewModel() {
                        Key = x.ProcurementOrderId,
                        Code = x.Code,
                        IsPrinted = x.IsPrinted,
                        PrintedDatetime = x.PrintedDate,
                        VendorCode = x.Vendor.Code,
                        VendorName = x.Vendor.Name,
                        OrderStatus = MethodHelper.GetEnumsDescription(typeof(AuditStatus), x.Status),
                        AuditedBy = x.AuditedBy,
                        AuditedDatetime = x.AuditedDatetime,
                        CreatedBy = x.CreatedBy,
                        CreatedDatetime = x.CreatedDatetime,
                        ModifiedBy = x.ModifiedBy,
                        ModifiedDatetime = x.ModifiedDatetime
                    };
                }).ToList();
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("获取采购订单列表失败！");
            }
        }

        public void Insert(ProcurementOrder procurementOrder) {
            try {
                procurementOrder.ProcurementOrderId = Guid.NewGuid().GetHashCode();
                procurementOrder.CreatedDatetime = DateTime.Now;
                procurementOrder.Status = (int)AuditStatus.Waiting;
                procurementOrder.ProcurementOrderDetails.ToList().ForEach(x => {
                    x.CreatedBy = procurementOrder.CreatedBy;
                    x.CreatedDatetime = procurementOrder.CreatedDatetime;
                    x.ProcurementOrderDetailsId = Guid.NewGuid().GetHashCode();
                });
                this._procurementOrderRepository.Insert(procurementOrder);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("插入新采购订单失败！");
            }
        }

        public void Update(ProcurementOrder procurementOrder) {
            try {
                ProcurementOrder oldProcurementOrder = this.FetchProcurementOrderById(procurementOrder.ProcurementOrderId);
                if (!oldProcurementOrder.RowVersion.SequenceEqual(procurementOrder.RowVersion)) {
                    throw this.BuildException("更新采购订单失败，数据不一致性错误！");
                }
                procurementOrder.ModifiedDatetime = DateTime.Now;
                this._procurementOrderRepository.UpdateProcurementOrder(procurementOrder);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("更新采购订单失败！");
            }
        }

        public void Delete(ProcurementOrder procurementOrder) {
            try {
                this._procurementOrderRepository.Delete(procurementOrder);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("删除采购订单失败！");
            }
        }

        public void Audit(ProcurementOrder procurementOrder) {
            try {
                ProcurementOrder oldProcurementOrder = this.FetchProcurementOrderById(procurementOrder.ProcurementOrderId);
                if (!oldProcurementOrder.RowVersion.SequenceEqual(procurementOrder.RowVersion)) {
                    throw this.BuildException("审核采购订单失败，数据不一致性错误！");
                }
                procurementOrder.AuditedDatetime = DateTime.Now;
                this._procurementOrderRepository.UpdateProcurementOrder(procurementOrder);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("审核采购订单失败！");
            }
        }

        public void Delete(params int[] procurementOrderIds) {
            try {
                this._procurementOrderRepository.DeleteMultipleProcurementOrder(procurementOrderIds);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("删除采购订单失败！");
            }
        }

        public int GetTheMaxFlowNumber(string startString) {
            try {
                return this._procurementOrderRepository.GetTheMaxFlowNumber(startString) + 1;
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("获取采购订单最大流水号失败！");
            }
        }

        public void SaveGeneratedProdurementOrder(List<ProcurementOrder> procurementOrderList,
            List<MidProcurementOrder> midProcurementOrderList) {
            try {
                ProduceConductProcessor produceConductProcessor = new ProduceConductProcessor();
                List<ProduceConduct> produceConductList = new List<ProduceConduct>();
                midProcurementOrderList.ForEach(x => {
                    if (!produceConductList.Any(y => y.ProduceConductId == x.ProduceConductId)) {
                        ProduceConduct produceConduct = produceConductProcessor.FetchProduceConductById(x.ProduceConductId);
                        produceConduct.IsCompleted = true;
                        produceConduct.ProcurementOrderId = x.ProcurementOrderId;
                        produceConductList.Add(produceConduct);
                    }
                });
                this._procurementOrderRepository.SaveGeneratedProdurementOrder(procurementOrderList, produceConductList);
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("保存自动生成的采购单失败！");
            }
        }

        public List<MidProcurementOrder> GenerateProdurementOrder() {
            try {
                Basic basic = new BasicsProcessor()
                    .FetchEnabledBasicsByType(BasicsType.ProcurementSourceType)
                    .Where(x => x.BasicsId != 0)
                    .FirstOrDefault();
                List<MidProcurementOrder> midList = this._procurementOrderRepository.GenerateProdurementOrder();
                midList.ForEach(x => {
                    x.ErrorMsg = x.MaterialId.HasValue
                        ? x.VendorId.HasValue
                            ? x.Vendors.Count < 2
                                ? string.Empty
                                : "需要确定供应商"
                            : "请建立并审核对应的报价单"
                        : "请建立并审核对应的 BOM 资料";
                    x.IsValid = x.MaterialId.HasValue && x.VendorId.HasValue;
                    if (basic != null) { x.SourceId = basic.BasicsId; }
                });
                return midList.OrderBy(x => x.ErrorMsg).ToList();
            }
            catch (Exception ex) {
                Logger.Error(ex.Message, ex);
                throw this.BuildException("自动生成采购订单失败！");
            }
        }
    }
}
